package gambit.core;

import java.util.ArrayList;

public class Tabuleiro {
	
	private int[] casas = new int[32];
	private int numPecasAprisionadas = 0;
	
	public Tabuleiro(){
		for(int i = 0; i < 12; i++){
			setValorCasa(i, 1);
			setValorCasa(31-i, -1);
		}
	}
	
	public Tabuleiro(int[] casas){
		for(int i = 0; i < 32; i++){
			this.casas[i] = casas[i];
		}
	}
	
	public Tabuleiro(int[] casas, int numMovimentos){
		for(int i = 0; i < 32; i++){
			this.casas[i] = casas[i];
		}
		this.numPecasAprisionadas = numMovimentos;
	}
	
	public ArrayList<Tabuleiro> listarPossiveisJogadas(){
		
		ArrayList<Tabuleiro> jogadasSimples = new ArrayList<Tabuleiro>();
		ArrayList<Tabuleiro> jogadasComAprisionamento = new ArrayList<Tabuleiro>();
		ArrayList<Tabuleiro> jogadasComMaisMovimentos = new ArrayList<Tabuleiro>();			
		boolean damaNova = false;

		for(int casaAtual: getMinhasCasas()){
			
			for(int proxCasa: proximasCasas(casaAtual)){
				
				Tabuleiro jogada = new Tabuleiro(casas);
				
				if(getValorCasa(casaAtual) == 1){
					
					if(isCasaVazia(proxCasa)){
						
						if(proxCasa >= 28) {
							jogada.setValorCasa(proxCasa, 2);
							damaNova = true;							
						}
						else {
							jogada.setValorCasa(proxCasa, 1);
						}
						jogada.setValorCasa(casaAtual, 0);
						jogadasSimples.add(jogada);
					}
					
					else if(isCasaOponente(proxCasa)){
						
						int outraCasa = proxCasaAoComerPeca(casaAtual, proxCasa);
						
						if(isValida(outraCasa) && isCasaVazia(outraCasa)){
							
							if(outraCasa >= 28) {
								jogada.setValorCasa(outraCasa, 2);
								damaNova = true;
							}
							else {
								jogada.setValorCasa(outraCasa, 1);
							}
							
							jogada.setValorCasa(proxCasa, 0);
							jogada.setValorCasa(casaAtual, 0);
							jogada.setNumPecasAprisionadas(jogada.getNumPecasAprisionadas() + 1);
							jogadasComAprisionamento.add(jogada);
							if(!damaNova) 
								jogadasComAprisionamento = jogada.maisJogadas(jogadasComAprisionamento, outraCasa);
						}
					}
				}
				
				if(getValorCasa(casaAtual) == 2){
					
					if(isCasaVazia(proxCasa)){
						
						jogada.setValorCasa(proxCasa, 2);
						jogada.setValorCasa(casaAtual, 0);
						jogadasSimples.add(jogada);
					}
					
					if(isCasaOponente(proxCasa)){
						
						int outraCasa = proxCasaAoComerPeca(casaAtual, proxCasa);
						
						if(isValida(outraCasa) && isCasaVazia(outraCasa)){
							
							jogada.setValorCasa(outraCasa, 2);
							jogada.setValorCasa(proxCasa, 0);
							jogada.setValorCasa(casaAtual, 0);
							jogada.setNumPecasAprisionadas(jogada.getNumPecasAprisionadas() + 1);
							jogadasComAprisionamento.add(jogada);
							jogadasComAprisionamento = jogada.maisJogadas(jogadasComAprisionamento, outraCasa);
						}
					}
				}
			}
		}
		
		if(jogadasComAprisionamento.size() > 0) {
			
			int maxMovimentos = 0;
			for(Tabuleiro t: jogadasComAprisionamento){

				if(t.getNumPecasAprisionadas() > maxMovimentos){
					maxMovimentos = t.getNumPecasAprisionadas();
					jogadasComMaisMovimentos.clear();
					jogadasComMaisMovimentos.add(t);
				}
				else if(t.getNumPecasAprisionadas() == maxMovimentos){
					jogadasComMaisMovimentos.add(t);
				}
			}
			return jogadasComMaisMovimentos;
		}
		else return jogadasSimples;
	}
	
	
	
	private ArrayList<Tabuleiro> maisJogadas(ArrayList<Tabuleiro> listaTab, int casaAtual){
		
		boolean damaNova = false;
		
		for(int proxCasa: proximasCasas(casaAtual)){
			Tabuleiro jogada = new Tabuleiro(this.casas, this.numPecasAprisionadas);
			
			if(isCasaOponente(proxCasa)){
				int outraCasa = proxCasaAoComerPeca(casaAtual, proxCasa);
				
				if(isValida(outraCasa) && isCasaVazia(outraCasa)){
					
					if(outraCasa >= 28 && jogada.getValorCasa(casaAtual) == 1) {
						jogada.setValorCasa(outraCasa, 2);
						damaNova = true;
					}
					else {
						jogada.setValorCasa(outraCasa, jogada.getValorCasa(casaAtual));
					}
					jogada.setValorCasa(proxCasa, 0);
					jogada.setValorCasa(casaAtual, 0);
					jogada.setNumPecasAprisionadas(jogada.getNumPecasAprisionadas() + 1);
					listaTab.add(jogada);
					if(!damaNova)
						listaTab = jogada.maisJogadas(listaTab, outraCasa);
				}
			}	
		}
		
		return listaTab;
	}
	
	
	public static Tabuleiro inverter(Tabuleiro tabuleiro){
		int buf;
		Tabuleiro tabInv = new Tabuleiro(tabuleiro.getCasas());
		
		for(int i = 0; i < 16; i++){
			buf = tabInv.casas[i];
			tabInv.casas[i] = tabInv.casas[31-i];
			tabInv.casas[31-i] = buf;
		}
		for(int i = 0; i < 32; i++){
			tabInv.casas[i] = - tabInv.casas[i];
		}
		return tabInv;
	}
	
	
	private int[] proximasCasas(int casaAtual){		
		int[] arr = new int[4];

		switch (casaAtual){
		case 4:
		case 5:
		case 6:
		case 12:
		case 13:
		case 14:
		case 20:
		case 21:
		case 22:
			if(getValorCasa(casaAtual) > 1){
				arr[0] = casaAtual+5;
				arr[1] = casaAtual+4;
				arr[2] = casaAtual-3;
				arr[3] = casaAtual-4;
			}
			if(getValorCasa(casaAtual) == 1){
				arr = new int[2];
				arr[0] = casaAtual+5;
				arr[1] = casaAtual+4;
			}
			break;
		case 9:
		case 10:
		case 11:
		case 17:
		case 18:
		case 19:
		case 25:
		case 26:
		case 27:
			if(getValorCasa(casaAtual) > 1){
				arr[0] = casaAtual+4;
				arr[1] = casaAtual+3;
				arr[2] = casaAtual-4;
				arr[3] = casaAtual-5;
			}
			if(getValorCasa(casaAtual) == 1){
				arr = new int[2];
				arr[0] = casaAtual+4;
				arr[1] = casaAtual+3;
			}
			break;
		case 0:
			arr = new int[1];
			arr[0] = 4;
			break;
		case 1:
		case 2:
		case 3:
			arr = new int[2];
			arr[0] = casaAtual+4;
			arr[1] = casaAtual+3;
			break;
		case 7:
		case 8:
		case 15:
		case 16:
		case 23:
		case 24:
			if(getValorCasa(casaAtual) > 1){
				arr = new int[2];
				arr[0] = casaAtual+4;
				arr[1] = casaAtual-4;
			}
			if(getValorCasa(casaAtual) == 1){
				arr = new int[1];
				arr[0] = casaAtual+4;
			}			
			break;
		case 28:
		case 29:
		case 30:
			if(getValorCasa(casaAtual) > 1){
				arr = new int[2];
				arr[0] = casaAtual-4;
				arr[1] = casaAtual-3;
			}
			else arr = null;
			break;
		case 31:
			if(getValorCasa(casaAtual) > 1){
				arr = new int[1];
				arr[0] = 27;
			}
			else arr = null;
			break;
		default:
			arr = null;
			break;
		}
		
		return arr;
	}
	
	private int proxCasaAoComerPeca(int minhaCasa, int casaOponente){
		int casa = -1;
		
		switch(minhaCasa){
		case 0:
			if(casaOponente == 4) casa = 9;
			break;
		case 1:
			if(casaOponente == 4) casa = 8;
			if(casaOponente == 5) casa = 10;
			break;
		case 2:
			if(casaOponente == 5) casa = 9;
			if(casaOponente == 6) casa = 11;
			break;
		case 3:
			if(casaOponente == 6) casa = 10;
			break;
		case 4:
			if(casaOponente == 9) casa = 13;
			break;
		case 5:
			if(casaOponente == 9) casa = 12;
			if(casaOponente == 10) casa = 14;
			break;
		case 6:
			if(casaOponente == 10) casa = 13;
			if(casaOponente == 11) casa = 15;
			break;
		case 7:
			if(casaOponente == 11) casa = 14;
			break;
		case 8:
			if(casaOponente == 4) casa = 1;
			if(casaOponente == 12) casa = 17;
			break;
		case 9:
			if(casaOponente == 4) casa = 0;
			if(casaOponente == 5) casa = 2;
			if(casaOponente == 12) casa = 16;
			if(casaOponente == 13) casa = 18;
			break;
		case 10:
			if(casaOponente == 5) casa = 1;
			if(casaOponente == 6) casa = 3;
			if(casaOponente == 13) casa = 17;
			if(casaOponente == 14) casa = 19;
			break;
		case 11:
			if(casaOponente == 6) casa = 2;
			if(casaOponente == 14) casa = 18;
			break;
		case 12:
			if(casaOponente == 9) casa = 5;
			if(casaOponente == 17) casa = 21;
			break;
		case 13:
			if(casaOponente == 9) casa = 4;
			if(casaOponente == 10) casa = 6;
			if(casaOponente == 17) casa = 20;
			if(casaOponente == 18) casa = 22;
			break;
		case 14:
			if(casaOponente == 18) casa = 21;
			if(casaOponente == 19) casa = 23;
			if(casaOponente == 10) casa = 5;
			if(casaOponente == 11) casa = 7;
			break;
		case 15:
			if(casaOponente == 11) casa = 6;
			if(casaOponente == 19) casa = 22;
			break;
		case 16:
			if(casaOponente == 12) casa = 9;
			if(casaOponente == 20) casa = 25;
			break;
		case 17:
			if(casaOponente == 12) casa = 8;
			if(casaOponente == 13) casa = 10;
			if(casaOponente == 20) casa = 24;
			if(casaOponente == 21) casa = 26;
			break;
		case 18:
			if(casaOponente == 21) casa = 25;
			if(casaOponente == 22) casa = 27;
			if(casaOponente == 13) casa = 9;
			if(casaOponente == 14) casa = 11;
			break;
		case 19:
			if(casaOponente == 22) casa = 26;
			if(casaOponente == 14) casa = 10;
			break;
		case 20:
			if(casaOponente == 17) casa = 13;
			if(casaOponente == 25) casa = 29;
			break;
		case 21:
			if(casaOponente == 17) casa = 12;
			if(casaOponente == 18) casa = 14;
			if(casaOponente == 25) casa = 28;
			if(casaOponente == 26) casa = 30;
			break;
		case 22:
			if(casaOponente == 18) casa = 13;
			if(casaOponente == 19) casa = 15;
			if(casaOponente == 26) casa = 29;
			if(casaOponente == 27) casa = 31;
			break;
		case 23:
			if(casaOponente == 19) casa = 14;
			if(casaOponente == 27) casa = 30;
			break;
		case 24:
			if(casaOponente == 20) casa = 17;
			break;
		case 25:
			if(casaOponente == 20) casa = 16;
			if(casaOponente == 21) casa = 18;
			break;
		case 26:
			if(casaOponente == 21) casa = 17;
			if(casaOponente == 22) casa = 19;
			break;
		case 27:
			if(casaOponente == 22) casa = 18;
			break;
		case 28:
			if(casaOponente == 25) casa = 21;
			break;
		case 29:
			if(casaOponente == 25) casa = 20;
			if(casaOponente == 26) casa = 22;
			break;
		case 30:
			if(casaOponente == 26) casa = 21;
			if(casaOponente == 27) casa = 23;
			break;
		case 31:
			if(casaOponente == 27) casa = 22;
			break;
		default:
			break;		
		}
		
		return casa;
	}
	
	public int[] getMinhasCasas(){
		int num = 0;
		
		for(int valor: casas){
			if(valor > 0) num = num + 1;
		}
		
		int[] arr = new int[num];
		for(int i = 0, n = 0; i < 32; i++){
			if(casas[i] > 0){
				arr[n] = i;
				n++;
			}
		}
		return arr;
	}
	
	public int getValorCasa(int casa){
		return this.casas[casa];
	}
	
	public void setValorCasa(int casa, int valor){
		this.casas[casa] = valor;
	}
	
	public boolean isMinhaCasa(int pos){
		return casas[pos] > 0;
	}
	
	public boolean isCasaVazia(int pos){
		return casas[pos] == 0;
	}
	
	public boolean isCasaOponente(int pos){
		return casas[pos] < 0;
	}
	
	public boolean isValida(int pos){
		return pos >= 0;
	}
	
	public int[] getCasas(){
		return casas;
	}

	public int getNumPecasAprisionadas() {
		return numPecasAprisionadas;
	}

	public void setNumPecasAprisionadas(int numMovimentos) {
		this.numPecasAprisionadas = numMovimentos;
	}

	public void setCasas(int[] casas) {
		this.casas = casas;
	}
	
//	public static boolean isIgual(Tabuleiro a, Tabuleiro b){
//		boolean c = true;
//		
//		for(int i = 0; i < 32 && c; i++){
//			c = a.getCasas()[i] == b.getCasas()[i];
//		}
//		
//		return c;
//	}

}
